剑指Offer 9 斐波那契数列

题目描述

大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。

思路

  1. 斐波那契数列在讲的时候就是为了引入递归,f(n)=f(n-1)+f(n-2),天生的递归啊,但问题是,递归需要消耗大量栈的空间,所有递归都需要等待底层的运算完毕;
  2. 递归不行,那就循环呗

    代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    public static void main(String [] arg)
    {
    System.out.println(Fibonacci1(3));
    }
    static public int Fibonacci(int n) {
    if ( n<= 0 )
    return 0 ;
    if (n == 1 )
    return 1;
    else
    return Fibonacci(n-1)+Fibonacci(n-2);
    }
    static public int Fibonacci1 (int n)
    {
    if ( n<2)
    return n;
    int x= 0;
    int y = 1;
    int test = 0;
    for ( int i=n;i>=2;i--)
    {
    test = x+y;
    x=y;
    y=test;
    }
    return test;
    }

变种1

一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路

从后往前想,每次下楼,都有两种选择,这个树形和斐波那契几乎一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int JumpFloor(int target) {
if (target<=2)
return target;
int x = 1;
int y = 1;
int test = 0;
for (int i = target;i>=2;i--)
{
test = x+y;
x=y;
y=test;
}
return test;
}

变种2

一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路

其实,如果还按照刚才的想法就会变得很难,因为要有两层循环,而找到规律的话,只需要这样:

1
2
3
public int JumpFloorII(int target) {
return 1<<--target;
}

如果是一脉相承的思路的话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public int JumpFloorII(int target) {
if(target == 0) {
return 0;
}
int[] dp = new int[target + 1];
dp[0] = 1;
dp[1] = 1;
for(int i = 2;i <= target;i++) {
dp[i] = 0;
for(int j = 0;j < i;j++) {
dp[i] += dp[j];
}
}
return dp[target];
}

收获

  1. 递归和循环的区别;递归还是用在比较简单或者真的无法用循环的时候,而且递归代码量很少,自然也就写起来很爽,但也容易看不懂